package org.redswallow.filter.plugin;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import org.redswallow.util.Utils;
import org.redswallow.util.config.IPropertySet;

public abstract class AbstractParameterCheckPlugin implements Plugin {

	private static final String CONFIG_INCLUDE_PARAMPATTENS = "includeParamPatterns";
    private static final String CONFIG_EXCLUDE_PARAMPATTENS = "excludeParamPatterns";
    
    //对指定参数进行检查或者不检查
	private final boolean includeParamsPatterns;
	
	//指定的参数规则表达式
	private final Collection<Pattern> paramNamePatterns;

	protected AbstractParameterCheckPlugin(IPropertySet config) {
		
		//检查有无指定的参数
		String includeParamPatternsString = config.getString(CONFIG_INCLUDE_PARAMPATTENS, null);
		String excludeParamPatternsString = config.getString(CONFIG_EXCLUDE_PARAMPATTENS, null);
		
		if (Utils.isNonBlank(includeParamPatternsString) && Utils.isNonBlank(excludeParamPatternsString) ) {
			throw new IllegalArgumentException("Can't specify both "+CONFIG_INCLUDE_PARAMPATTENS+" and "+CONFIG_EXCLUDE_PARAMPATTENS);
		}
		
		if (Utils.isBlank(includeParamPatternsString)) {
			includeParamsPatterns = false;
			paramNamePatterns = parsePatterns(excludeParamPatternsString);
		}else {
			includeParamsPatterns = true;
			paramNamePatterns = parsePatterns(includeParamPatternsString);
		}
		
	}
	
	protected static Collection<Pattern> parsePatterns(String patternsString) {
		if (patternsString == null) {
			return Collections.emptyList();
		}
		List<Pattern> patterns = new ArrayList<Pattern>(5);
		for (String pattern : patternsString.split(",")) {
			if (pattern.length() > 0) {
				patterns.add(Pattern.compile(pattern));
			}
		}
		return Collections.unmodifiableList(patterns);
	}
	
	protected abstract boolean checkParam(String name, Map<String,String[]> map, ServletResponse response) ;
	
	@Override
	public boolean invoke(ServletRequest request, ServletResponse response) {
		
		Map<String, String[]> params = request.getParameterMap();
		
		//没有参数不做检查
		if (params.size()==0) return true;
		
		for(String name : params.keySet()) {
			
			if (isTargetParam(name)) {
				
				if (!checkParam(name, params, response)) return false;
				
			}
			
		}
		
		
		return true;
	}
	
	private boolean isTargetParam(String name) {
		if (name != null) {
			for (Pattern pattern : paramNamePatterns) {
				if (pattern.matcher(name).matches()) {
					return includeParamsPatterns;
				}
			}
		}
		return !includeParamsPatterns;
	}
	
}
